home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Software Vault: The Games Collection 1
/
software vault.zip
/
software vault
/
CDR10
/
YICN23.ZIP
/
UNITS
/
ICON.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1993-02-21
|
14KB
|
441 lines
#include <fstream.h>
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <mem.h>
#include <dos.h>
#include <alloc.h>
#include <io.h>
#include <stdlib.h>
#include "xlib.h"
#include "xrect.h"
#include "xpbitmap.h"
#include "xcbitmap.h"
#include "xpal.h"
#include "icon.h"
int widthFour(int width)
{
return (width + (((4-(width % 4)) == 4) ? 0 : (4-(width%4)))); //smallest mult of 4 > width!
}
char * unRollBlt(char * rolledBlt, int & iwidth, int & iheight)
{
char * temp = NULL;
int * width = (int *)&rolledBlt[0];
iwidth = *width;
int * height = (int *)&rolledBlt[2];
iheight = *height;
char * tempimage = &rolledBlt[4];
int row, col, i, j, k, width4;
int heightCounter, widthCounter;
width4 = widthFour(*width);
int newHeight = *height;
temp = new char[width4*newHeight + 4];
if (temp == NULL) {delete temp; return NULL;}
temp[0] = (width4)/4;
temp[1] = *height;
k = 2;
for (i=0; i<4; i++)
for (heightCounter = 0; heightCounter < *height; heightCounter +=1)
for (widthCounter=0; widthCounter < width4; widthCounter += 4, k++)
{
if (((widthCounter + i) >= *width))
temp[k] = 0;
else
temp[k] = tempimage[i + (heightCounter* *width) + widthCounter];
}
return (char far *)temp;
}
char * rollBlt(char * unRolledBlt, int & iwidth, int &iheight)
{
int width4 = 4*unRolledBlt[0];
int height = unRolledBlt[1];
char *returnBuffer = new char [iwidth * iheight + 4];
if (returnBuffer == NULL)
return NULL;
*(int *)&returnBuffer[0] = iwidth;
*(int *)&returnBuffer[2] = iheight;
int k = 2;
for (int i = 0; i < 4; ++i) //each of the four loops!
for(int heightCounter = 0; heightCounter < height; ++heightCounter)
for(int widthCounter = 0; widthCounter < width4; widthCounter += 4)
{
if (widthCounter + i < iwidth)
returnBuffer[i + heightCounter*iwidth + widthCounter + 4] = unRolledBlt[k];
k++;
}
return(returnBuffer);
}
char far *
AllocatedSprite(int logicalWidth, char * bitmap)
{
char * result;
int size;
result = new char[(bitmap[0] * bitmap[1] * 7) / 2 + 25];
if (result == 0)
return(0);
size = x_compile_bitmap(logicalWidth, bitmap, result);
return (char far *)farrealloc(result, size);
}
byte icon::getPixel(int x, int y)
{
int width4 = 4*unrolledPic[0];
return unrolledPic[((x % 4)*(width4*height/4) + x/4 + y*width4/4) +2 ];
}
void icon::hide(int x, int y, word toOffset, word fromOffset)
{
x_cp_vid_rect(x, y, x+(width), y+height, x, y,
fromOffset, toOffset,
ScrnLogicalPixelWidth,ScrnLogicalPixelWidth);
}
void icon::show(int x, int y, word offset)
{
if (unrolledPic != NULL)
{
if (flags == normal)
x_put_pbm(x, y, offset, unrolledPic);
else if (flags == fast)
x_put_cbitmap(x, y, offset, unrolledPic);
}
}
void icon::showMasked(int x, int y, word offset)
{
if (unrolledPic != NULL)
{
if (flags == normal)
x_put_masked_pbm(x, y, offset, unrolledPic);
else if (flags == fast)
x_put_cbitmap(x, y, offset, unrolledPic);
}
}
void icon::save(char * filename)
{
long miscNumber = 0;
long bufferIndex = 0;
if (flags != fast)
{
ofstream myOutStream(filename, ios::out | ios::binary);
if (myOutStream)
{
myOutStream.write("YARFILE ", 10);
myOutStream.write((char *) &width, sizeof(width));
myOutStream.write((char *) &height, sizeof(height));
int width4 = widthFour(width);
for (long bytesLeft = (long)width4 * (long)height + 2; bytesLeft > 0;)//
{
miscNumber = (bytesLeft < 32000) ? bytesLeft : 32000;
myOutStream.write(unrolledPic + bufferIndex, (int)miscNumber);
bytesLeft -= miscNumber;
bufferIndex += miscNumber;
}
myOutStream.close();
}
}
}
char *icon::useData(unsigned char * myPointer, flagType iflags)
//for use with bin2hdr files!!
{
if (unrolledPic)
delete unrolledPic;
flags = iflags;
width = *(int *) &myPointer[10];
height = *(int *) &myPointer[12];
if (flags == normal)
{
int width4 = widthFour(width);
unrolledPic = new char[width4 * height + 2];//
memcpy(unrolledPic, &myPointer[14], (width4 * height + 2));//
makeCollisionMap();
return(unrolledPic);
}
else if (flags == fast)
{
char * tempRolled = rollBlt(myPointer + 14, width, height);
tempRolled[2] = (char) width;
tempRolled[3] = (char) height;
unrolledPic = AllocatedSprite(ScrnLogicalPixelWidth/4, tempRolled + 2);
delete tempRolled;
makeCollisionMap();
return(unrolledPic);
}
else return(NULL);
}
char * icon::load(char * filename, flagType iflags, yakLib * myYakLib)
{
char * tempBuffer = NULL;
if (myYakLib)
tempBuffer = myYakLib->loadToMem(filename);
else
tempBuffer = loadDosToMem(filename);
if ((tempBuffer == NULL) || (strncmp(tempBuffer, "YARFILE", 7)))
{
unrolledPic = NULL;
return(NULL);
}
else
{
char* tempReturnValue = useData(tempBuffer, iflags);
delete tempBuffer;
return tempReturnValue;
}
}
//collision code goes in here.
//the cbox map array is in [y][x] format, in order to use the more elegant
//and very fast bitwise operators. This is contrary to the familiar icon
//bitmap [x][y] structure.
int icon::setWPacked(int xwid, int y1)
{
int x8 = (xwid >> 3) + ((xwid & 7) > 0);
if (collisionMap) delete collisionMap;
collisionMap = new byte[x8 * y1];
if (collisionMap == NULL)
return 0;
else
byteWidth = x8;
return 1;
}
int icon::setCollisionBit(int ix, int iy, booleanFlags flag)
{
byte bitPixel = 128; // ie 1000 0000
bitPixel >>= ix % 8; // right shift it...
if (flag == on)
collisionMap[iy * byteWidth + (int)(ix/8)] |= bitPixel;
else if (flag == off)
collisionMap[iy * byteWidth + (int)(ix/8)] &= ~bitPixel;
return bitPixel;
}
int icon::getCollisionBit(int ix, int iy)
{
byte bitPixel = 128;
bitPixel >>= ix%8;
return (collisionMap[iy * byteWidth + (int)(ix/8)] & bitPixel) ? 1 : 0;
}
void icon::spewCollisionTable(void)
{
for (int heightCounter = 0; heightCounter < height; ++heightCounter)
{
for (int widthCounter = 0; widthCounter < byteWidth*8; ++widthCounter)
cout << getCollisionBit(widthCounter, heightCounter);
cout << '\n';
}
}
int icon::makeCollisionMap()
{
setWPacked(width, height);
for (int heightCounter = 0; heightCounter < height; ++heightCounter)
for (int widthCounter = 0; widthCounter < byteWidth*8; ++widthCounter)
setCollisionBit(widthCounter, heightCounter, (getPixel(widthCounter, heightCounter) == 0) ? off : on);
return 1;
}
int icon::hitXY(int myX, int myY, icon* target, int targetX, int targetY)
{
int overlapTop = (myY > targetY) ? myY : targetY;
int overlapBottom = (myY+height > targetY + target->height) ?
(targetY + target->height) :
(myY + height);
if (overlapTop > overlapBottom) return 0;
int overlapLeft = (myX > targetX) ? myX : targetX;
int overlapRight = (myX + width > targetX + target->width) ?
(targetX + target->width) :
(myX + width);
int overlapWidth = overlapRight - overlapLeft;
if (overlapWidth < 0) return 0;
int overlapByteWidth = (overlapWidth >> 3) + ((overlapWidth & 7) > 0);
//now we know what the tops and bottoms of the overlap are. Now our
//task is to find the offsets in each collisionMap to start checking.
byte * myOffset = collisionMap, * targetOffset = target->collisionMap;
myOffset += (myY > targetY) ? 0 : byteWidth*(overlapTop - myY); //y part
myOffset += (myX > targetX) ? 0 : (overlapLeft - myX) >> 3;
targetOffset += (targetY > myY) ? 0 : target->byteWidth*(overlapTop - targetY);
targetOffset += (targetX > myX) ? 0 : (overlapLeft - targetY) >> 3;
int myStep = byteWidth - overlapByteWidth;
int targetStep = target->byteWidth - overlapByteWidth;
int shift = (7 - (overlapWidth & 7));
for (int heightCounter = overlapTop; heightCounter <= overlapBottom; ++heightCounter)
{
for (int widthCounter = 0; widthCounter < overlapByteWidth; ++ widthCounter)
{
if ((myX < targetX) ?
(*myOffset & (*targetOffset >> shift)) :
(*myOffset & (*targetOffset << shift))) return 1;
++myOffset;
++targetOffset;
}
myOffset += myStep;
targetOffset += targetStep;
}
return 0;
}
//icon zooming code goes here----------------------------------------->
byte ** icon::zoomTable = NULL;
int icon::zoomTableWidth = 0;
byte ** icon::setZoomTable(int newWidth)
{
float interval = 0;
float tempNumber = 0, secondTempNumber = 0;
if (zoomTable)
delete zoomTable;
zoomTable = new byte*[newWidth];
if (!zoomTable) return NULL;
for (int counter = 0; counter < newWidth; ++counter)
zoomTable[counter] = new byte[newWidth];
if (!zoomTable[newWidth - 1]) return NULL;
zoomTableWidth = newWidth;
for (int heightCounter = 0; heightCounter < newWidth; ++heightCounter)
{
interval = (((float)newWidth) / ((float)heightCounter+1)); //+1 for div by 0
tempNumber = secondTempNumber = 0;
for (int widthCounter = 0; widthCounter < newWidth; ++widthCounter)
{
secondTempNumber = ((float)widthCounter + 1) / interval;
if ((secondTempNumber - tempNumber) >= 1)
{
zoomTable[heightCounter][widthCounter] = 1;
tempNumber += 1;
}
else
zoomTable[heightCounter][widthCounter] = 0;
}
}
return zoomTable;
}
void icon::spewZoomTable(void)
{
for (int heightCounter = 0; heightCounter < zoomTableWidth; ++heightCounter)
{
for (int widthCounter = 0; widthCounter < zoomTableWidth; ++widthCounter)
cout << (int)zoomTable[heightCounter][widthCounter];
cout << '\n';
}
}
icon * icon::zoomedIcon(int newWidth)
{
int numberOfDots = newWidth / zoomTableWidth; //number of times each dot is drawn
int tempPosition = newWidth % zoomTableWidth - 1; //position in zoom table
if (tempPosition < 0)
{
numberOfDots--;
tempPosition = zoomTableWidth - 1;
}
byte * zoomReference = zoomTable[tempPosition];
int width4 = widthFour(newWidth);
byte * zoomedIcon = new byte[width4 * newWidth + 2];
if (!zoomedIcon)
return NULL;
*(byte *)&zoomedIcon[0] = (byte)(widthFour(newWidth)/4);
*(byte *)&zoomedIcon[1] = (byte)(newWidth);
byte * currentZoomedPointer = zoomedIcon+2; //current position in new buffer
byte * currentUnzoomedPointer = unrolledPic+2;
int zoomedFourCounter = 0; //what step of the four strings we're on
int unzoomedFourCounter = 0;
int zoomedInterval = (zoomedIcon[0]*zoomedIcon[1]); //how much to increment
int zoomedInterval4 = 4*zoomedInterval;
int unzoomedInterval = (unrolledPic[0]*unrolledPic[1]); //our pointers
int unzoomedInterval4 = 4*unzoomedInterval;
byte * tempLinePointer = NULL; //we need this to duplicate lines
int heightCounter, widthCounter, lineCounter, dotCounter;
int dotsDone = 0;
int linesDone = 0;
for (heightCounter = 0; heightCounter < zoomTableWidth; ++heightCounter)
{
for (lineCounter = 0,tempLinePointer = currentUnzoomedPointer; lineCounter < (numberOfDots + zoomReference[heightCounter]); ++lineCounter)
{
++linesDone;
currentUnzoomedPointer = tempLinePointer;
dotsDone = 0;
for (widthCounter = 0; widthCounter < zoomTableWidth; ++widthCounter)
{
for (dotCounter = 0; dotCounter < (numberOfDots + zoomReference[widthCounter]); ++dotCounter)
{
*currentZoomedPointer = *currentUnzoomedPointer;
zoomedFourCounter++;
currentZoomedPointer += zoomedInterval;
if (zoomedFourCounter == 4)
{
zoomedFourCounter = 0;
currentZoomedPointer -= (zoomedInterval4 - 1);
}
++dotsDone;
}
unzoomedFourCounter++;
currentUnzoomedPointer += unzoomedInterval;
if (unzoomedFourCounter == 4)
{
unzoomedFourCounter = 0;
currentUnzoomedPointer -= (unzoomedInterval4 - 1);
}
}
for (;dotsDone < width4; ++dotsDone)
{
*currentZoomedPointer = 0;
zoomedFourCounter++;
currentZoomedPointer += zoomedInterval;
if (zoomedFourCounter == 4)
{
zoomedFourCounter = 0;
currentZoomedPointer -= (zoomedInterval4 - 1);
}
}
}
currentUnzoomedPointer = tempLinePointer + unrolledPic[0];
}
for (;linesDone < newWidth; ++linesDone)
{
for (dotsDone = 0; dotsDone < width4; ++dotsDone)
{
*currentZoomedPointer = 0;
zoomedFourCounter++;
currentZoomedPointer += zoomedInterval;
if (zoomedFourCounter == 4)
{
zoomedFourCounter = 0;
currentZoomedPointer -= (zoomedInterval4 - 1);
}
}
}
icon * returnIcon = new icon;
returnIcon->unrolledPic = zoomedIcon;
returnIcon->flags = icon::normal;
returnIcon->width = returnIcon->height = newWidth;
returnIcon->collisionMap = NULL;
return returnIcon;
}
void icon::showZoomed(int x, int y, word offset, int newWidth)
{
icon * tempIcon = zoomedIcon(newWidth);
tempIcon->showMasked(x, y, offset);
delete tempIcon;
}